package detect.parse.tree;

import java.util.ArrayList;
import java.util.List;

import detect.Log;
import detect.parse.pattern.MethodsPattern;
import detect.parse.tree.token.TokenList;
import detect.parse.tree.token.RawTokenType;

public class ForExpression extends Expression {	
	
	Expression initExp=null;
	ConditionExpression condExp=null;
	Expression iterExp=null;
	BlockExpression body=null;
	public TreeType getType(){
		return TreeType.ForType;
	}
	public ForExpression(){
	}
	
	@Override
	public List<FunctionCallExpression> getSubFunctionCallExpressionList(){
		List<FunctionCallExpression> subFunCallList=new ArrayList<FunctionCallExpression>();
		subFunCallList.addAll(iterExp.getSubFunctionCallExpressionList());
		return subFunCallList;
	}
	
	@Override
	public void findInnerPatterns(){
		initExp.findInnerPatterns();
		condExp.findInnerPatterns();
		iterExp.findInnerPatterns();
		body.findInnerPatterns();
		
		patterns.addAll(initExp.patterns);
		patterns.addAll(condExp.patterns);
		patterns.addAll(iterExp.patterns);
		patterns.addAll(body.patterns);
		
		for(Expression subIterExp: iterExp.getSubFunctionCallExpressionList()){
			if(subIterExp.getType()==TreeType.FunctionCallType){
				FunctionCallManager.putFunction(subIterExp);
				//iter-iter
				patterns.add(new MethodsPattern((FunctionCallExpression)subIterExp,(FunctionCallExpression)subIterExp,MethodsPattern.ITERATE_CALL));
				for(Expression subBodyExp: body.getSubFunctionCallExpressionList()){
					if(subBodyExp.getType()==TreeType.FunctionCallType){
						FunctionCallManager.putFunction(subBodyExp);
						patterns.add(new MethodsPattern((FunctionCallExpression)subIterExp,(FunctionCallExpression)subBodyExp,MethodsPattern.SEQUENCE_CALL));
					}
				}
			}
		}
		
		//body-body
		for(Expression subBodyExp: body.expList){
			if(subBodyExp.getType()==TreeType.FunctionCallType){
				patterns.add(new MethodsPattern((FunctionCallExpression)subBodyExp,(FunctionCallExpression)subBodyExp,MethodsPattern.ITERATE_CALL));
			}
		}
	}
	
	public ForExpression(TokenList _tokenList,Expression _initExp,ConditionExpression _condExp,Expression _iterExp,BlockExpression _body){
		tokenList=_tokenList;
		initExp=_initExp;
		condExp=_condExp;
		iterExp=_iterExp;
		body=_body;		
	}
	
	@Override
	public Expression getExpression(TokenList _tokenList){
		Log.incIndence();
		Log.printTree(this.getType().toString());
		tokenList=_tokenList;
		
		int semiTokenIndex=tokenList.indexOf(RawTokenType.SEMI);
		TokenList initTokenList=tokenList.subList(2, semiTokenIndex);
		
		int preLastPos=semiTokenIndex;
		semiTokenIndex=tokenList.indexOf(RawTokenType.SEMI,semiTokenIndex+1);
		TokenList condTokenList=tokenList.subList(preLastPos+1, semiTokenIndex);
		
		preLastPos=semiTokenIndex;
		//semiTokenIndex=tokenList.indexOf(RawTokenType.RightBraceType,semiTokenIndex+1);
		semiTokenIndex=tokenList.findMatchRightBrace(1, RawTokenType.LPAREN, RawTokenType.RPAREN);
		TokenList iterTokenList=tokenList.subList(preLastPos+1, semiTokenIndex);
		
		preLastPos=semiTokenIndex;
		
		TokenList bodyTokenList=tokenList.subList(preLastPos+1);
		
		Expression _initExp=ExpressionFactory.expInstance.getExpression(initTokenList);
		Expression _condExp=ExpressionFactory.condExpInstance.getExpression(condTokenList);
		Expression _iterExp=ExpressionFactory.expInstance.getExpression(iterTokenList);
		Expression _body=ExpressionFactory.blockExpInstance.getExpression(bodyTokenList);
		
		Log.decIndence();
		return new ForExpression(
				_tokenList,
				_initExp,
				(ConditionExpression)_condExp,
				_iterExp,
				(BlockExpression)_body);
	}
}
